package com.dingding.order.core.grab.biz.impl;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.http.HttpStatus;
import org.apache.log4j.Logger;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.common.core.base.dto.AbstractResponse;
import com.dingding.common.core.base.dto.ResponseEntity;
import com.dingding.common.core.beans.Userordert;
import com.dingding.common.core.config.ServiceCode;
import com.dingding.common.core.util.DateFormatUtil;
import com.dingding.common.core.util.ToolUtil;
import com.dingding.facade.user.dto.usercoupon.ResCoupon;
import com.dingding.facade.user.service.IUserInfoFacade;
import com.dingding.facde.coupon.ICouponService;
import com.dingding.order.code.GrabOrderCodeMsg;
import com.dingding.order.core.grab.biz.IGrabOrderService;
import com.dingding.order.core.grab.biz.INoticeUserService;
import com.dingding.order.core.grab.dao.IGrabOrderDao;
import com.dingding.order.dto.grab.ReqUserGrabOrderDTO;
import com.dingding.order.dto.grab.ResUserGrabOrder;

/**
 * @ClassName: CompetitiveOrderServiceImpl
 * @Description: 用户抢单Service实现类
 * @author YHQ
 * @date 2016年6月4日 下午5:18:28
 */
@Component("grabOrderService")
public class GrabOrderServiceImpl extends AbstractResponse<ResUserGrabOrder,ReqUserGrabOrderDTO> implements IGrabOrderService {

	private Logger log = Logger.getLogger(this.getClass());

	@Resource(name = "userInfoService")
	private IUserInfoFacade userInfoFacade; // 用户信息

	@Resource(name = "noticeUserService")
	private INoticeUserService noticeUserService;// 用户抢单通知接口(发送短信和推送消息)

	@Resource(name = "grabOrderDao")
	private IGrabOrderDao grabOrderDao;

	@Resource(name="couponService")
	private ICouponService couponService;
	
	/**
	 * 
	 * @Title: userGrabOrder
	 * @Description: 用户抢单总方法
	 * @author YHQ
	 * 
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public String userGrabOrder(String requestData) {

		ResponseEntity<ResUserGrabOrder> response = new ResponseEntity<ResUserGrabOrder>();

		ReqUserGrabOrderDTO reqUserGrabOrderDTO = super.parseRequestJson(requestData);
		
		// 1.判断参数是否存在空值
		if (!validateParam(response, reqUserGrabOrderDTO)) {
			return super.responseBeanToJson(response);
		}
		// 判断是否符合抢单条件
		if (!grabConditions(response, reqUserGrabOrderDTO)) {
			return super.responseBeanToJson(response);
		}
		// 用户抢单操作
		Userordert userordert = grabOrder(response, reqUserGrabOrderDTO);

		// 判断抢单操作是否成功
		if (userordert != null) {

			noticeUserService.getNoticeUserInfo(userordert.getOrderType(), userordert.getPlaceOrderUserId(),
					reqUserGrabOrderDTO.getGrabOrderUserId(), userordert.getOid(),userordert.getParentOrder());

		}

		return super.responseBeanToJson(response);

	}

	/**
	 * 
	 * @Title: grabConditions
	 * @Description: 判断是否符合抢单条件
	 * @author YHQ
	 * @return boolean true 符合条件 false 不符合条件
	 * 
	 */
	public boolean grabConditions(ResponseEntity<ResUserGrabOrder> response, ReqUserGrabOrderDTO reqUserGrabOrderDTO) {

		// 获取当前订单是否存在
		Userordert ordert = getUserOrdert(reqUserGrabOrderDTO.getOid());

		// 判断当前订单是否存在。
		if (ordert == null) {
			response.setCode(HttpStatus.SC_FORBIDDEN);
			response.setErrorMessage(GrabOrderCodeMsg.ORDER_NOT_EXISTS);
			response.setPromptMessage(GrabOrderCodeMsg.ORDER_NOT_EXISTS);
			return false;
		}

		// 判断当前订单状态是否是待抢单状态。
		if (ordert.getOrderStatus() > 2 || (ordert.getOrderStatus() == 2 && ordert.getIsChildren() != 1)) {

			response.setCode(HttpStatus.SC_FORBIDDEN);
			response.setErrorMessage(GrabOrderCodeMsg.ORDER_NOT_WAIT_GRAB);
			response.setPromptMessage(GrabOrderCodeMsg.ORDER_NOT_WAIT_GRAB);

			return false;
		}
		
		// 判断当前用户是否存在未完成订单。
		List<Userordert> userorderts = getUserOrders(reqUserGrabOrderDTO.getGrabOrderUserId(),
				reqUserGrabOrderDTO.getIsLongDistance());

		// 判断当前是否存在未完成订单
		if (userorderts != null && userorderts.size() > 0) {

			boolean flag = false;

			// 遍历全部订单，判断其中是否有合乘订单
			for (Userordert userordert : userorderts) {
				// 如果有订单为合乘订单，则返回true
				if (userordert.getIsCarShare() == 2) {
					flag = true;
				}
				
				//判断抢单人是否有被抢订单的订单类型
				if(userordert.getIsLongDistance() == ordert.getIsLongDistance()){
					
					if(userordert.getIsCarShare() == ordert.getIsCarShare()){

						//判断出发时间是否在同一天
						boolean sameDay = DateFormatUtil.isSameDate(userordert.getSetOutTime(), ordert.getSetOutTime());
						
						if(!sameDay){
							response.setCode(HttpStatus.SC_FORBIDDEN);
							response.setErrorMessage(GrabOrderCodeMsg.ORDER_NOT_SAME_DAY);
							response.setPromptMessage(GrabOrderCodeMsg.ORDER_NOT_SAME_DAY);
							return false;
						}
						
					}else{	//如果一个是合乘一个不是合乘，则终止抢单
						response.setCode(HttpStatus.SC_FORBIDDEN);
						response.setErrorMessage(GrabOrderCodeMsg.ORDER_NOT_MATCHING);
						response.setPromptMessage(GrabOrderCodeMsg.ORDER_NOT_MATCHING);
						return false;
					}
				}
				
			}

			// 用户抢单用户为乘客，则不能再次抢单
			if (reqUserGrabOrderDTO.getUserType() == 2) {
				response.setCode(HttpStatus.SC_FORBIDDEN);
				response.setErrorMessage(GrabOrderCodeMsg.EXISTS_NOT_COMPLETED_ORDER);
				response.setPromptMessage(GrabOrderCodeMsg.EXISTS_NOT_COMPLETED_ORDER);
				return false;
			}

			// 判断订单是否为合乘订单
			if (!flag) {
				response.setCode(HttpStatus.SC_FORBIDDEN);
				response.setErrorMessage(GrabOrderCodeMsg.EXISTS_NOT_COMPLETED_ORDER);
				response.setPromptMessage(GrabOrderCodeMsg.EXISTS_NOT_COMPLETED_ORDER);
				return false;
			}
		}

		return true;
	}

	/**
	 * 
	 * @Title: getUserOrders
	 * @Description: 获取用户未完成订单列表
	 * @param @return
	 *            设定文件
	 * @author YHQ
	 * @return List<Userordert> 返回类型
	 * 
	 */
	public List<Userordert> getUserOrders(String userId, Integer isLongDistance) {

		// 创建用于存储未完成订单的对象
		List<Userordert> userorderts = new ArrayList<Userordert>();

		// 添加获取用户未完成订单列表
		Criterion criterion = Restrictions.and(Restrictions.or(Restrictions.eq("placeOrderUserId", userId),
				Restrictions.eq("grabOrderUserId", userId)), Restrictions.eq("isLongDistance", isLongDistance));

		try {
			userorderts = grabOrderDao.queryCriteriaList(criterion);
		} catch (Exception e) {
			log.error("根据用户Id和订单类型（长途或短途）时出现异常    类：" + this.getClass() + " getUserOrders()", e);
		}

		return userorderts;
	}

	/**
	 * 
	 * @Title: getUserOrdert
	 * @Description: 根据订单Id获取订单信息
	 * @param oid
	 *            订单Id
	 * @author YHQ
	 * @return Userordert 返回类型
	 * L
	 */
	public Userordert getUserOrdert(String oid) {

		try {
			return grabOrderDao.getById(oid);
		} catch (Exception e) {
			log.error("根据订单Id获取订单信息时出现异常   类：" + this.getClass() + " getUserOrdert()", e);
		}

		return null;
	}

	/**
	 * 
	 * @Title: grabOrder
	 * @Description: 用户抢单
	 * @author YHQ
	 * @return void
	 * 
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Userordert grabOrder(ResponseEntity<ResUserGrabOrder> response, ReqUserGrabOrderDTO reqUserGrabOrderDTO) {

		// 获取带抢订单信息
		Userordert userordert = grabOrderDao.getById(reqUserGrabOrderDTO.getOid());

		if (userordert == null) {
			return null;
		}

		String ucid = null;
		
		//判断是否有优惠券
		if(ToolUtil.isNotBlank(reqUserGrabOrderDTO.getUcId()) || ToolUtil.isNotBlank(userordert.getUcId())){
			
			if(ToolUtil.isNotBlank(reqUserGrabOrderDTO.getUcId())){
				ucid = reqUserGrabOrderDTO.getUcId();
			}else{
				ucid = userordert.getUcId();
			}
		}
		
		// 获取优惠券信息
		ResCoupon resCoupon = userInfoFacade.getResCoupon(ucid);
		
		// 修改主订单
		Userordert parentOrder = parentOrder(userordert, reqUserGrabOrderDTO, response);

		// 判断父订单是否为空
		if (parentOrder == null) {
			return null;
		}

		// 修改子订单
		Userordert subOrder = subOrdert(resCoupon, userordert, parentOrder, reqUserGrabOrderDTO, response);

		// 判断子订单是否为空
		if (subOrder == null) {
			return null;
		}

		if (resCoupon != null && ToolUtil.isNotBlank(resCoupon.getUcId())) {
			// 修改优惠券信息
			userInfoFacade.updateUserCoupon(resCoupon.getUcId());
		}

		//父订单Id
		subOrder.setParentOrder(subOrder.getParOrderId());
		
		return subOrder;
	}

	/**
	 * 
	 * 抢单后更新订单状态为已抢单
	 * 
	 * @Title: updateCacheOrderStatus
	 * @author CHEHAUNBO
	 * 
	 */
	public synchronized void updateCacheOrderStatus(String orderId) {

		// TODO 1:获取缓存中的订单信息

	}

	/**
	 * 
	 * @Title: parentOrder 
	 * @Description: 父订单 
	 * @param userordert 订单信息
	 * @param reqUserGrabOrderDTO 客户端请求参数
	 * @author YHQ 
	 * @return Userordert    返回类型
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * 
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Userordert parentOrder(Userordert userordert, ReqUserGrabOrderDTO reqUserGrabOrderDTO,
			ResponseEntity<ResUserGrabOrder> response) {

		Userordert driverOrder = null;

		// 如果是司机下单，则需要获取车主订单信息(主订单)
		if (userordert.getOrderType() == 1) {

			driverOrder = userordert;

			// 判断是否座满
			if (userordert.getIsCarShare() == 2 && userordert.getFreeSeat() <= 0 && userordert.getOrderType() == 2) {
				response.setCode(HttpStatus.SC_NOT_FOUND);
				response.setErrorMessage(GrabOrderCodeMsg.FULL_STARFFED);
				response.setPromptMessage(GrabOrderCodeMsg.FULL_STARFFED);
				return null;
			}

			// 判断座位数是否满足
			if (userordert.getFreeSeat() - reqUserGrabOrderDTO.getAboardNumber() < 0) {
				response.setCode(HttpStatus.SC_NOT_FOUND);
				response.setErrorMessage(GrabOrderCodeMsg.INSUFFICIENT_STARFFED);
				response.setPromptMessage(GrabOrderCodeMsg.INSUFFICIENT_STARFFED);
				return null;
			}

			userordert.setFreeSeat(driverOrder.getFreeSeat() - reqUserGrabOrderDTO.getAboardNumber());// 当前车辆空闲位置

		} else if (userordert.getOrderType() == 2) {// 乘客下单

			// 获取司机待完成订单
			List<Userordert> passengerOrders = grabOrderDao.getUserOrdertByUserId(
					reqUserGrabOrderDTO.getGrabOrderUserId(), reqUserGrabOrderDTO.getIsLongDistance());

			if (passengerOrders.size() <= 0) {

				driverOrder = new Userordert();

				try {
					BeanUtils.copyProperties(driverOrder, userordert);
				} catch (IllegalAccessException e) {
					log.error("将userordert内容赋值给driverOrder时出现异常 类：" + this.getClass(), e);
				} catch (InvocationTargetException e) {
					log.error("将userordert内容赋值给driverOrder时出现异常 类：" + this.getClass(), e);
				}

				driverOrder.setOid(ToolUtil.getUid());// 订单Id
				driverOrder.setPlaceOrderUserId(reqUserGrabOrderDTO.getGrabOrderUserId());
				driverOrder.setIsChildren(1);// 1:父订单 2:子订单
				driverOrder.setLastDate(null);

			} else {

				// false:没有抢过该订单 true:抢过该订单
				boolean flag = false;

				// 遍历司机的待完成订单
				for (Userordert ordert : passengerOrders) {

					// 判断当前订单是否已经被抢过
					if (ordert.getOid().equals(userordert.getOid())) {
						flag = true;
						break;
					}

					// 获取主订单对象
					if ((ordert.getOrderStatus() == 1) || (ordert.getOrderStatus() == 2 && ordert.getIsChildren() == 1)) {
						driverOrder = ordert;
						driverOrder.setLastDate(null);
					}
				}

				// 判断是否已经抢过该订单
				if (flag) {
					response.setCode(HttpStatus.SC_NOT_FOUND);
					response.setErrorMessage(GrabOrderCodeMsg.ALREADY_GRAB_ORDER);
					response.setPromptMessage(GrabOrderCodeMsg.ALREADY_GRAB_ORDER);
					return null;
				}
			}
		}

		// 非合乘订单，修改订单状态
		if(driverOrder.getIsCarShare() == 1){
			driverOrder.setOrderStatus(ServiceCode.ORDER_STATUS_PAY);
		}
		
		try {

			if (driverOrder != null) {
				driverOrder.setOrderStatus(2);
				grabOrderDao.saveOrUpdate(driverOrder);
			}

		} catch (Exception e) {
			log.error("用户抢单修改订单信息时出现异常   类：" + this.getClass() + " parentOrder()", e);
			response.setErrorMessage(GrabOrderCodeMsg.UPDATE_PARENT_GRAB_ORDER_ERRRO);
		}

		return driverOrder;
	}

	/**
	 * @Title: getUserOrdertByOther
	 * @Description: 用户抢单生成新订单(子订单)
	 * @param userordert 订单信息
	 * @param resCoupon 优惠券信息
	 * @param reqUserGrabOrderDTO 客户端请求参数
	 * @author YHQ
	 * @return Userordert 返回类型
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Userordert subOrdert(ResCoupon resCoupon, Userordert userordert, Userordert driverordert,
			ReqUserGrabOrderDTO reqUserGrabOrderDTO, ResponseEntity<ResUserGrabOrder> response) {

		Userordert order = new Userordert();

		try {
			// 乘客下单
			if (userordert.getOrderType() == 2) {

				order = userordert;

				// 主订单ID
				order.setParOrderId(driverordert.getOid());
			} else {// 司机下单
				BeanUtils.copyProperties(order, driverordert);

				// 司机下单，重新添加一个子订单
				order.setOid(ToolUtil.getUid());
				//父订单Id
				order.setParOrderId(driverordert.getOid());
				order.setLastDate(null);
			}
		} catch (IllegalAccessException e1) {
			log.error("用户抢单时产生子订单出现异常  类：" + this.getClass(), e1);
			return null;
		} catch (InvocationTargetException e1) {
			log.error("用户抢单时产生子订单出现异常  类：" + this.getClass(), e1);
			return null;
		}

		// 2:已被抢（待支付）
		order.setOrderStatus(ServiceCode.ORDER_STATUS_PAY);
		// 抢单用户
		order.setGrabOrderUserId(reqUserGrabOrderDTO.getGrabOrderUserId());
		// 抢单时间
		order.setGrabOrderTime(new Date());
		// 座位数
		order.setFreeSeat(reqUserGrabOrderDTO.getAboardNumber());

		// 判断是否为乘客
		if (reqUserGrabOrderDTO.getUserType() == 2) {

			if (resCoupon != null) {
				order.setUcId(resCoupon.getUcId());// 用户优惠券Id
				order.setCouponMoney(new BigDecimal(resCoupon.getCouponMoney()));// 优惠金额
			}
		}

		order.setIsChildren(2);// 1:父订单 2:子订单

		// 非合乘订单，修改订单状态
		if(order.getIsCarShare() == 1){
			order.setOrderStatus(ServiceCode.ORDER_STATUS_PAY);
		}
		
		try {

			grabOrderDao.saveOrUpdate(order);

		} catch (Exception e) {
			log.error("用户抢单修改订单信息时出现异常   类：" + this.getClass() + " subOrdert()", e);
			response.setErrorMessage(GrabOrderCodeMsg.UPDATE_SUB_GRAB_ORDER_ERRRO);
			return null;
		}

		// 用户抢单响应参数
		ResUserGrabOrder resUserGrabOrder = new ResUserGrabOrder();

		resUserGrabOrder.setSystemTime(new Date());//系统时间
		resUserGrabOrder.setGrabOrderTime(order.getGrabOrderTime());//抢单时间
		resUserGrabOrder.setParentOrder(driverordert.getOid());//父订单Id
		resUserGrabOrder.setSubOrder(order.getOid());//子订单Id

		response.setResponseBody(resUserGrabOrder);

		return order;
	}

	@Override
	public String driverGrabOrder(String requestData) {
		// TODO Auto-generated method stub
		return null;
	}

	
}
